package com.blue.http.server;

import com.blue.http.config.HttpConfig;
import com.blue.http.config.SSLConfig;
import com.blue.http.config.WebsocketConfig;
import com.blue.http.util.HttpException;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.task.TaskExecutor;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerKeepAliveHandler;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;

/**
 * HTTP初始化器
 * 
 * @author zhengj
 * @since 1.0 2017年3月14日
 */
public class HttpInitializer extends ChannelInitializer<SocketChannel> implements InitializingBean
{
	private static Logger logger = LoggerFactory.getLogger(HttpInitializer.class);

	private TaskExecutor taskExecutor;
	private HttpConfig httpConfig;
	private WebsocketConfig websocketConfig;
	private SSLConfig sslConfig;

	public HttpInitializer()
	{
	}

	@Override
	protected void initChannel(SocketChannel ch) throws Exception
	{
		ChannelPipeline cp = ch.pipeline();

		if (sslConfig != null)
		{
			cp.addLast(sslConfig.getSslContext().newHandler(ch.alloc()));
		}

		cp.addLast(new HttpServerCodec());
		cp.addLast(new HttpServerKeepAliveHandler());

		if (httpConfig != null)
		{
			cp.addLast(new ChunkedWriteHandler());
			cp.addLast(new HttpServerHandler(taskExecutor, httpConfig, websocketConfig));
		}

		if (websocketConfig != null)
		{
			cp.addLast(new HttpObjectAggregator(Short.MAX_VALUE * 10));
			cp.addLast(new WebSocketServerProtocolHandler(websocketConfig.getRoot(), null, true));
			cp.addLast(new WebsocketServerHandler(taskExecutor, websocketConfig));
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception
	{
		if (httpConfig == null && websocketConfig == null)
			throw new HttpException("HttpConfig 和 WebsocketConfig 不能同时为空");

		if (taskExecutor == null)
			throw new HttpException("TaskExecutor 不能为空");
	}

	public void setHttpConfig(HttpConfig httpConfig)
	{
		this.httpConfig = httpConfig;
	}

	public void setWebsocketConfig(WebsocketConfig websocketConfig)
	{
		this.websocketConfig = websocketConfig;
	}

	public void setSslConfig(SSLConfig sslConfig)
	{
		this.sslConfig = sslConfig;
	}

	public void setTaskExecutor(TaskExecutor taskExecutor)
	{
		this.taskExecutor = taskExecutor;
	}
}
